#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <string.h>

#define HTTP_PORT "HTTP_PORT"
#define HTTP_READ_HEADERS_TIMEOUT "HTTP_READ_HEADERS_TIMEOUT"

#define ERR_ALARM "Nelze nastavit budik."
#define ERR_MEM "Nelze alokovat operacni pamet."
#define ERR_CONF_FILE "Nebyl nalezen konfiguracni soubor."
#define ERR_CONF_FILE2 "Chyba konfiguracniho souboru."
#define ERR_HTTP_HEADERS "Nelze nacist HTTP hlavicky."
#define ERR_ARGS "Zadejte prosim spravny pocet argumentu."
#define ERR_HTTP_FILENAME "Nepodarilo se rozhodnout, jaky soubor je vlastne pozadovan."
#define KILLER_NOTE1 "Zabijime ...\n"
#define KILLER_NOTE2 "Byl zabit proces: "
#define DEATH_NOTE1 "Volani z funkce: "
#define DEATH_NOTE2 "Hlaska: "
#define ERR_CLIENT "Klient neposlal zadna data."
#define ERR_CLIENT2 "Doslo k chybe pri cekani na data od klienta."
#define MSG_TERMINATION "Koncime..."

#define JEREMY_VERSION "0.9.1"
#define DEBUG true

/* Hlavni struktura jeremyu */
struct main_structure {
	int client_fd;
	int server_fd;
	int http_port;
	char client_addr[256];
	char * requested_filename;
};

/* Struktura obsahujici strom nastaveni */
struct settings {
	char * name;
	char * value;
	struct settings * next_settings;
};


/* Hlavni programove funkce */
void death(char * msg, const char * function);

/* Funkce pro praci se siti */
int wait_for_client(struct main_structure * jeremy);
int start_server(struct main_structure * jeremy);
int read_byte_from_client(struct main_structure * jeremy, char * byte);
int set_http_read_headers_timeout(struct main_structure * jeremy, struct settings * nastaveni);
int read_line_from_client(struct main_structure * jeremy, char line[]);

/* Funkce pro praci s nastavenim */
int add_settings(struct settings * tree, char * name, char * value);
struct settings * get_settings(struct settings * tree, char * name);
int num_settings(struct settings * tree);
int conf_file_parser(struct settings * tree, char file[]);

/* Funkce pro praci s procesy */
pid_t make_child(struct main_structure * jeremy);
void kill_zombie(int n);
void termination(int n);

/* Funkce pro praci s http */
int http_read_headers(struct main_structure * jeremy, struct settings * headers, struct settings * nastaveni); 
int http_read_header_line(int fd, char * result, int max_res_len);
int http_header_get_name(char * line, char * header_name);
int http_header_get_value(char * line, char * header_value);
int http_check_min_headers(struct main_structure * jeremy, struct settings * headers);
int http_requested_filename(struct main_structure * jeremy, struct settings * headers);
int http_requested_query_string(struct main_structure * jeremy, struct settings * headers);
